Webframeworkk/ASP.NET Core/Filter
Filters sind leistungsstarke Komponenten in ASP.NET Core MVC, mit denen Sie Code vor, nach oder sogar während der Ausführung Ihrer Controller-Aktionen oder Razor-Pages abfangen und ausführen können. Sie bieten eine saubere und modulare Methode zur Implementierung von Cross-Cutting Concerns (querschnittlichen Belangen).
1. Warum Filter verwenden?
Filter helfen dabei, die Logik Ihrer Anwendung sauber zu trennen:
- Kapselung: Wiederverwendbare Logik wird gekapselt, was Code-Duplikate reduziert.
- Saubere Trennung: Controller-Aktionen bleiben auf ihre Kernaufgabe (Anfragen bearbeiten) fokussiert.
- Erweiterbarkeit: Sie können problemlos eigene Filter für spezifische Anforderungen erstellen.
Typische Einsatzbereiche:
- Authentifizierung & Autorisierung: Überprüfung der Benutzeridentität und -rechte.
- Caching: Speichern von Antworten zur Leistungssteigerung.
- Fehlerbehandlung: Zentrales Abfangen von Ausnahmen.
- Logging: Protokollierung von Anfragen und Antworten.
- Action-Modifikation: Manipulieren von Parametern oder Ergebnissen.
2. Die Filter-Pipeline und Typen
Es gibt fünf Haupttypen von Filtern, die in einer bestimmten Reihenfolge ausgeführt werden:
- Authorization Filter: Bestimmen, ob ein Benutzer berechtigt ist. (Zuerst ausgeführt)
- Resource Filter: Laufen nach der Autorisierung; ideal für Caching oder Model Binding Manipulationen.
- Action Filter: Laufen unmittelbar vor und nach der Ausführung einer Action-Methode.
- Exception Filter: Werden ausgeführt, wenn eine unbehandelte Ausnahme auftritt.
- Result Filter: Laufen unmittelbar vor und nach der Ausführung des Action-Ergebnisses (IActionResult).
Der Spezialfall: IAlwaysRunResultFilter
Im Gegensatz zu normalen Result-Filtern wird dieser Filter immer ausgeführt, auch wenn ein vorheriger Filter die Pipeline kurzgeschlossen (short-circuited) hat.
3. Action Filter im Detail
Dies ist der am häufigsten verwendete Filtertyp. Er implementiert das Interface IActionFilter (synchron) oder IAsyncActionFilter (asynchron).
Beispiel: Ein einfacher Logging-Filter
public class PersonsListActionFilter : IActionFilter
{
private readonly ILogger<PersonsListActionFilter> _logger;
public PersonsListActionFilter(ILogger<PersonsListActionFilter> logger)
{
_logger = logger;
}
public void OnActionExecuting(ActionExecutingContext context)
{
// Logik VOR der Action-Ausführung
_logger.LogInformation("Vor der Ausführung der Action.");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Logik NACH der Action-Ausführung
_logger.LogInformation("Nach der Ausführung der Action.");
}
}
4. Anwendung und Registrierung
Sie können Filter auf drei Ebenen anwenden:
Global (in Program.cs)
Gilt für alle Controller und Aktionen im gesamten Projekt.
builder.Services.AddControllersWithViews(options => {
options.Filters.Add(new MyGlobalFilter()); // Instanz
options.Filters.Add<MyGlobalFilter>(); // Typ
});
Controller-Ebene
Gilt für alle Aktionen innerhalb eines bestimmten Controllers.
[Route("[controller]")]
[TypeFilter(typeof(PersonsListActionFilter))]
public class PersonsController : Controller { ... }
Action-Ebene
Gilt nur für eine spezifische Action-Methode.
[TypeFilter(typeof(ResponseHeaderActionFilter))]
public IActionResult Index() { ... }
5. Reihenfolge der Ausführung (Ordering)
Standardmäßig folgt MVC einer festen Reihenfolge. Sie können diese jedoch mit der Order-Eigenschaft oder durch Implementierung von IOrderedFilter anpassen.
- Filter mit niedrigeren Werten werden zuerst ausgeführt.
[TypeFilter(typeof(MyFilter), Order = 1)]
6. Short-Circuiting (Kurzschließen)
Ein Filter kann die Pipeline vorzeitig beenden. Dies ist nützlich für Validierung oder Autorisierung.
- In Action Filtern: Setzen Sie
context.Result = new SomeResult();. Die Action-Methode wird dann nicht mehr aufgerufen.
7. ServiceFilter vs. TypeFilter
Wenn Ihr Filter Abhängigkeiten (Services) über Dependency Injection benötigt, stehen Ihnen zwei Attribute zur Verfügung:
| Feature | TypeFilter | ServiceFilter |
|----------------------|-------------------------------|----------------------------------------|
| Erstellung | Über ObjectFactory | Über den DI-Container |
| DI erforderlich? | Nein (nur für Abhängigkeiten) | Ja (Filter muss registriert sein) |
| Argumente | Unterstützt (via Arguments) | Unterstützt keine Argumente |
| Lifetime | Standardmäßig Transient | Definiert in Program.cs (Scoped, etc.) |
8. Filter vs. Middleware
Obwohl sie sich ähnlich sehen, gibt es wichtige Unterschiede:
- Middleware: Läuft in der gesamten ASP.NET Core-Pipeline für alle Anfragen. Sie hat Zugriff auf den
HttpContext, kennt aber keine MVC-Konzepte wieViewDataoderActionParameters. - Filter: Laufen nur innerhalb des MVC-Kontexts (unter dem Endpoint Middleware). Sie haben vollen Zugriff auf MVC-spezifische Daten.
Best Practices
- Wählen Sie den richtigen Filtertyp: Nutzen Sie Action Filter für Parameter und Resource Filter für Caching.
- Abhängigkeitsinjektion: Nutzen Sie DI, um Ihre Filter testbar und entkoppelt zu halten.
- Fokus behalten: Ein Filter sollte nur eine einzige, klar definierte Aufgabe haben.
- Performance beachten: Zu viele oder zu komplexe Filter können die Antwortzeit der Anwendung beeinträchtigen.
- IAlwaysRunResultFilter für Cleanup: Nutzen Sie diesen Typ für Aufgaben, die auch im Fehlerfall sicher ausgeführt werden müssen (z.B. Ressourcen freigeben).
Erstellt für Thorsten – Viel Erfolg beim Programmieren!